package cn.wizzer.app.web.commons.ext.websocket.main.monitor;

import cn.wizzer.framework.base.Result;
import cn.wizzer.framework.util.ClassUtil;
import io.netty.channel.ChannelHandlerContext;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 22099
 */
public abstract class BaseNettyMonitor {
    /**
     * class-实例
     */
    private static final Map<Class, cn.wizzer.app.web.commons.ext.websocket.main.monitor.BaseNettyMonitor> MONITORS = new HashMap<>();

    static {
        //启动注入
        String thisPackageName = cn.wizzer.app.web.commons.ext.websocket.main.monitor.BaseNettyMonitor.class.getPackage().getName();
        List<Class<?>> classListByAnnotation = ClassUtil.getClassListByAnnotation(thisPackageName.substring(0, thisPackageName.indexOf(".main")), NettyMonitor.class,true);

        for (Class<?> aClass : classListByAnnotation) {
            try {
                //创建实例
                aClass.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    protected BaseNettyMonitor() {
        NettyMonitor nettyMonitor = this.getClass().getAnnotation(NettyMonitor.class);
        if (nettyMonitor == null) {
            Result.breakWith(String.format("Non conforming class:%s\n Cause By Annotation NettyMonitor not found on the class;", this.getClass()));
        }
        MONITORS.put(this.getClass(),this);
    }

    public static BaseNettyMonitor instance(Class<? extends cn.wizzer.app.web.commons.ext.websocket.main.monitor.BaseNettyMonitor> clazz){
        return MONITORS.get(clazz);
    }

    public static Collection<BaseNettyMonitor> instances() {
        //排序
        return MONITORS.values().stream().sorted(Comparator.comparing(BaseNettyMonitor::order)).collect(Collectors.toList());
    }

    private static Integer order(BaseNettyMonitor monitor) {
        return monitor.getClass().getAnnotation(NettyMonitor.class).order();
    }

    public abstract void added(ChannelHandlerContext ctx);

    public abstract void removed(ChannelHandlerContext ctx);
}
